From ee86be040c5b3eed640bf4a3bd33a92c823d20d0 Mon Sep 17 00:00:00 2001 From: "djm@kirby.fc.hp.com" Date: Tue, 31 May 2005 20:54:20 +0000 Subject: [PATCH] bitkeeper revision 1.1564.1.5 (429ccefcMIcuaJH4b_1aAdD0JTIaMg) Two more hyperprivops Signed-off by: Dan Magenheimer --- xen/arch/ia64/hyperprivop.S | 162 ++++++++++++++++++++++++++++++++- xen/arch/ia64/privop.c | 32 +++++-- xen/arch/ia64/vcpu.c | 18 ++-- xen/include/public/arch-ia64.h | 5 +- 4 files changed, 197 insertions(+), 20 deletions(-) diff --git a/xen/arch/ia64/hyperprivop.S b/xen/arch/ia64/hyperprivop.S index 4c8ebb09fc..a33518e0ac 100644 --- a/xen/arch/ia64/hyperprivop.S +++ b/xen/arch/ia64/hyperprivop.S @@ -32,11 +32,45 @@ GLOBAL_ENTRY(fast_hyperprivop) // HYPERPRIVOP_RFI? cmp.eq p7,p6=XEN_HYPER_RFI,r17 (p7) br.sptk.many hyper_rfi;; - // if not rfi, give up for now and do it the slow way + +#if 0 + // HYPERPRIVOP_SSM_I? + cmp.eq p7,p6=XEN_HYPER_SSM_I,r17 +(p7) br.sptk.many hyper_ssm_i;; +#endif + +#if 1 +// hard to test, because only called from rbs_switch + // HYPERPRIVOP_COVER? + cmp.eq p7,p6=XEN_HYPER_COVER,r17 +(p7) br.sptk.many hyper_cover;; +#endif + +#if 0 // FIXME: This inexplicably causes the number of ssm_dt's to + // skyrocket, thus slowing down everything + // HYPERPRIVOP_SSM_DT? + cmp.eq p7,p6=XEN_HYPER_SSM_DT,r17 +(p7) br.sptk.many hyper_ssm_dt;; +#endif + +#if 1 + // HYPERPRIVOP_RSM_DT? + cmp.eq p7,p6=XEN_HYPER_RSM_DT,r17 +(p7) br.sptk.many hyper_rsm_dt;; +#endif + + // if not one of the above, give up for now and do it the slow way br.sptk.many dispatch_break_fault ;; // ensure that, if giving up, registers at entry to fast_hyperprivop unchanged ENTRY(hyper_rfi) +#define FAST_HYPERPRIVOP_CNT +#ifdef FAST_HYPERPRIVOP_CNT + movl r20=fast_hyperpriv_cnt+(8*XEN_HYPER_RFI);; + ld8 r21=[r20];; + adds r21=1,r21;; + st8 [r20]=r21;; +#endif adds r20=XSI_IPSR_OFS-XSI_PSR_IC_OFS,r18 ;; ld8 r21=[r20];; // r21 = vcr.ipsr extr.u r22=r21,IA64_PSR_BE_BIT,1 ;; @@ -101,3 +135,129 @@ ENTRY(hyper_rfi) ;; rfi ;; + +ENTRY(hyper_cover) +#ifdef FAST_HYPERPRIVOP_CNT + movl r20=fast_hyperpriv_cnt+(8*XEN_HYPER_COVER);; + ld8 r21=[r20];; + adds r21=1,r21;; + st8 [r20]=r21;; +#endif + mov r24=cr.ipsr + mov r25=cr.iip;; + // skip test for vpsr.ic.. it's a prerequisite for hyperprivops + cover ;; + adds r20=XSI_INCOMPL_REG_OFS-XSI_PSR_IC_OFS,r18 ;; + mov r30=cr.ifs;; + adds r22=XSI_IFS_OFS-XSI_PSR_IC_OFS,r18 + ld4 r21=[r20] ;; + cmp.eq p6,p7=r21,r0 ;; +(p6) st8 [r22]=r30;; +(p7) st4 [r20]=r0;; + mov cr.ifs=r0;; + // adjust return address to skip over break instruction + extr.u r26=r24,41,2 ;; + cmp.eq p6,p7=2,r26 ;; +(p6) mov r26=0 +(p6) adds r25=16,r25 +(p7) adds r26=1,r26 + ;; + dep r24=r26,r24,41,2 + ;; + mov cr.ipsr=r24 + mov cr.iip=r25 + mov pr=r31,-1 ;; + rfi + ;; + +#if 1 +// return from metaphysical mode (meta=1) to virtual mode (meta=0) +ENTRY(hyper_ssm_dt) +#ifdef FAST_HYPERPRIVOP_CNT + movl r20=fast_hyperpriv_cnt+(8*XEN_HYPER_SSM_DT);; + ld8 r21=[r20];; + adds r21=1,r21;; + st8 [r20]=r21;; +#endif + mov r24=cr.ipsr + mov r25=cr.iip;; + adds r20=XSI_METAPHYS_OFS-XSI_PSR_IC_OFS,r18 ;; + ld4 r21=[r20];; + cmp.eq p7,p0=r21,r0 // meta==0? +(p7) br.spnt.many 1f ;; // already in virtual mode + mov r22=IA64_KR(CURRENT);; + adds r22=IA64_VCPU_META_SAVED_RR0_OFFSET,r22;; + ld4 r23=[r22];; + mov rr[r0]=r23;; + srlz.i;; + st4 [r20]=r0 ;; + // adjust return address to skip over break instruction + extr.u r26=r24,41,2 ;; + cmp.eq p6,p7=2,r26 ;; +(p6) mov r26=0 +(p6) adds r25=16,r25 +(p7) adds r26=1,r26 + ;; + dep r24=r26,r24,41,2 + ;; + mov cr.ipsr=r24 + mov cr.iip=r25 +1: mov pr=r31,-1 ;; + rfi + ;; + +// go to metaphysical mode (meta=1) from virtual mode (meta=0) +ENTRY(hyper_rsm_dt) +#ifdef FAST_HYPERPRIVOP_CNT + movl r20=fast_hyperpriv_cnt+(8*XEN_HYPER_RSM_DT);; + ld8 r21=[r20];; + adds r21=1,r21;; + st8 [r20]=r21;; +#endif + mov r24=cr.ipsr + mov r25=cr.iip;; + adds r20=XSI_METAPHYS_OFS-XSI_PSR_IC_OFS,r18 ;; + ld4 r21=[r20];; + cmp.ne p7,p0=r21,r0 // meta==0? +(p7) br.spnt.many 1f ;; // already in metaphysical mode + mov r22=IA64_KR(CURRENT);; + adds r22=IA64_VCPU_META_RR0_OFFSET,r22;; + ld4 r23=[r22];; + mov rr[r0]=r23;; + srlz.i;; + adds r21=1,r0 ;; + st4 [r20]=r21 ;; + // adjust return address to skip over break instruction + extr.u r26=r24,41,2 ;; + cmp.eq p6,p7=2,r26 ;; +(p6) mov r26=0 +(p6) adds r25=16,r25 +(p7) adds r26=1,r26 + ;; + dep r24=r26,r24,41,2 + ;; + mov cr.ipsr=r24 + mov cr.iip=r25 +1: mov pr=r31,-1 ;; + rfi + ;; + +// enable interrupts (and also interrupt collection) +ENTRY(hyper_ssm_i) +#ifdef FAST_HYPERPRIVOP_CNT + movl r20=fast_hyperpriv_cnt+(8*XEN_HYPER_SSM_I);; + ld8 r21=[r20];; + adds r21=1,r21;; + st8 [r20]=r21;; +#endif + mov r24=cr.ipsr + mov r25=cr.iip;; + movl r20=0x100000001;; + st8 [r18]=r20;; // turn on both vpsr.i and vpsr.ic +// FIXME: NEED TO UPDATE IPSR/IIP TO SKIP BREAK INST +// FIXME: NEED TO CHECK FOR PENDING INTERRUPTS AND DELIVER THEM! +1: mov pr=r31,-1 ;; + rfi + ;; +#endif + diff --git a/xen/arch/ia64/privop.c b/xen/arch/ia64/privop.c index 0fba1d502f..d0be05d9e4 100644 --- a/xen/arch/ia64/privop.c +++ b/xen/arch/ia64/privop.c @@ -747,14 +747,16 @@ priv_emulate(VCPU *vcpu, REGS *regs, UINT64 isr) #define HYPERPRIVOP_COVER 0x4 #define HYPERPRIVOP_ITC_D 0x5 #define HYPERPRIVOP_ITC_I 0x6 -#define HYPERPRIVOP_MAX 0x6 +#define HYPERPRIVOP_SSM_I 0x7 +#define HYPERPRIVOP_MAX 0x7 char *hyperpriv_str[HYPERPRIVOP_MAX+1] = { - 0, "rfi", "rsm.dt", "ssm.dt", "cover", "itc.d", "itc.i", + 0, "rfi", "rsm.dt", "ssm.dt", "cover", "itc.d", "itc.i", "ssm.i", 0 }; -unsigned long hyperpriv_cnt[HYPERPRIVOP_MAX+1] = { 0 }; +unsigned long slow_hyperpriv_cnt[HYPERPRIVOP_MAX+1] = { 0 }; +unsigned long fast_hyperpriv_cnt[HYPERPRIVOP_MAX+1] = { 0 }; /* hyperprivops are generally executed in assembly (with physical psr.ic off) * so this code is primarily used for debugging them */ @@ -765,13 +767,12 @@ ia64_hyperprivop(unsigned long iim, REGS *regs) INST64 inst; UINT64 val; -// FIXME: Add instrumentation for these // FIXME: Handle faults appropriately for these if (!iim || iim > HYPERPRIVOP_MAX) { printf("bad hyperprivop; ignored\n"); return 1; } - hyperpriv_cnt[iim]++; + slow_hyperpriv_cnt[iim]++; switch(iim) { case HYPERPRIVOP_RFI: (void)vcpu_rfi(ed); @@ -793,6 +794,9 @@ ia64_hyperprivop(unsigned long iim, REGS *regs) inst.inst = 0; (void)priv_itc_i(ed,inst); return 1; + case HYPERPRIVOP_SSM_I: + (void)vcpu_set_psr_i(ed); + return 1; } return 0; } @@ -981,18 +985,28 @@ int dump_hyperprivop_counts(char *buf) { int i; char *s = buf; - s += sprintf(s,"Slow hyperprivops:\n"); + unsigned long total = 0; + for (i = 1; i <= HYPERPRIVOP_MAX; i++) total += slow_hyperpriv_cnt[i]; + s += sprintf(s,"Slow hyperprivops (total %d:\n",total); + for (i = 1; i <= HYPERPRIVOP_MAX; i++) + if (slow_hyperpriv_cnt[i]) + s += sprintf(s,"%10d %s\n", + slow_hyperpriv_cnt[i], hyperpriv_str[i]); + total = 0; + for (i = 1; i <= HYPERPRIVOP_MAX; i++) total += fast_hyperpriv_cnt[i]; + s += sprintf(s,"Fast hyperprivops (total %d:\n",total); for (i = 1; i <= HYPERPRIVOP_MAX; i++) - if (hyperpriv_cnt[i]) + if (fast_hyperpriv_cnt[i]) s += sprintf(s,"%10d %s\n", - hyperpriv_cnt[i], hyperpriv_str[i]); + fast_hyperpriv_cnt[i], hyperpriv_str[i]); return s - buf; } void zero_hyperprivop_counts(void) { int i; - for (i = 0; i <= HYPERPRIVOP_MAX; i++) hyperpriv_cnt[i] = 0; + for (i = 0; i <= HYPERPRIVOP_MAX; i++) slow_hyperpriv_cnt[i] = 0; + for (i = 0; i <= HYPERPRIVOP_MAX; i++) fast_hyperpriv_cnt[i] = 0; } #define TMPBUFLEN 8*1024 diff --git a/xen/arch/ia64/vcpu.c b/xen/arch/ia64/vcpu.c index ac933c6f6d..b55e5b6bd7 100644 --- a/xen/arch/ia64/vcpu.c +++ b/xen/arch/ia64/vcpu.c @@ -173,6 +173,7 @@ IA64FAULT vcpu_set_psr_dt(VCPU *vcpu) IA64FAULT vcpu_set_psr_i(VCPU *vcpu) { PSCB(vcpu,interrupt_delivery_enabled) = 1; + PSCB(vcpu,interrupt_collection_enabled) = 1; return IA64_NO_FAULT; } @@ -649,6 +650,7 @@ IA64FAULT vcpu_get_ivr(VCPU *vcpu, UINT64 *pval) #ifdef HEARTBEAT_FREQ #define N_DOMS 16 // period in seconds static long count[N_DOMS] = { 0 }; + static long nonclockcount[N_DOMS] = { 0 }; REGS *regs = vcpu_regs(vcpu); unsigned domid = vcpu->domain->domain_id; #endif @@ -670,15 +672,15 @@ IA64FAULT vcpu_get_ivr(VCPU *vcpu, UINT64 *pval) } #ifdef HEARTBEAT_FREQ if (domid >= N_DOMS) domid = N_DOMS-1; - if (vector == (PSCB(vcpu,itv) & 0xff) && - !(++count[domid] & ((HEARTBEAT_FREQ*1024)-1))) { - printf("Dom%d heartbeat... iip=%p,psr.i=%d,pend=%d\n", - domid, regs->cr_iip, - current->vcpu_info->arch.interrupt_delivery_enabled, - current->vcpu_info->arch.pending_interruption); - count[domid] = 0; - dump_runq(); + if (vector == (PSCB(vcpu,itv) & 0xff)) { + if (!(++count[domid] & ((HEARTBEAT_FREQ*1024)-1))) { + printf("Dom%d heartbeat... ticks=%lx,nonticks=%lx\n", + domid, count[domid], nonclockcount[domid]); + //count[domid] = 0; + //dump_runq(); + } } + else nonclockcount[domid]++; #endif // now have an unmasked, pending, deliverable vector! // getting ivr has "side effects" diff --git a/xen/include/public/arch-ia64.h b/xen/include/public/arch-ia64.h index ebae4b89c3..587487640f 100644 --- a/xen/include/public/arch-ia64.h +++ b/xen/include/public/arch-ia64.h @@ -82,10 +82,11 @@ typedef struct vcpu_guest_context { #endif /* !__ASSEMBLY__ */ #define XEN_HYPER_RFI 1 -#define XEN_HYPER_RSM_PSR_DT 2 -#define XEN_HYPER_SSM_PSR_DT 3 +#define XEN_HYPER_RSM_DT 2 +#define XEN_HYPER_SSM_DT 3 #define XEN_HYPER_COVER 4 #define XEN_HYPER_ITC_D 5 #define XEN_HYPER_ITC_I 6 +#define XEN_HYPER_SSM_I 7 #endif /* __HYPERVISOR_IF_IA64_H__ */ -- 2.30.2